﻿
namespace TestFsWeb

open System
open System.Net
open System.Threading
open Microsoft.FSharp.Control.WebExtensions

open Helper
open TestFsWeb.HttpListenerExtend

type HttpSvrAgent private (url,processor) as this =
    // **************************** primary constructor
    let m_cts = new CancellationTokenSource()
    let m_agent = MailboxProcessor<HttpListenerContext>.Start((fun _ -> processor this),m_cts.Token)
    let m_svrjob = async {
        use listener = new HttpListener()
        listener.Prefixes.Add url
        listener.Start()

        while true do
            let! context = listener.AsyncGetContext()
            m_agent.Post context
    }// async

    do
        Async.Start(m_svrjob,m_cts.Token)

    // **************************** members
    member this.Receive(?timeout) = 
        m_agent.Receive(?timeout=timeout)

    member this.Stop() =
        m_cts.Cancel()

    interface IDisposable with
        member this.Dispose() =
            (m_agent :> IDisposable).Dispose()

    static member Start(url,processor) =
        new HttpSvrAgent(url,processor)

module TestHttpSvrAgent=

    let svr_job (msg : string) (svr : HttpSvrAgent) = 
        async {
            let counter = ref 0

            while true do
                let! ctx = svr.Receive()
                incr counter

                let request = ctx.Request
                printfn "[%3d] %s %s\n" !counter request.HttpMethod request.RawUrl

                do! ctx.Response.AsyncReply msg
        }

    let private simple_svragent() =

        use agent = HttpSvrAgent.Start("http://localhost:50000/",(svr_job "<h1>hello F# from web</h1>"))
        printfn "HTTP server agent is running, ......"

        pause_for("exit")

    let private test_with_webclient() =
        let url = "http://localhost:50000/"

        use agent = HttpSvrAgent.Start(url,(svr_job "<h1>hello webclient</h1>"))
        printfn "HTTP server agent is running, ......"

        pause_for("start the client")
        async {
            let uri = new Uri(url)
            use client = new WebClient()

            for index = 1 to 10 do
                let! content = client.AsyncDownloadString uri
                printfn "\t client: [%3d] %s" index content
        } |> Async.StartImmediate

        pause_for("exit")

    let main() =
        // simple_svragent()
        test_with_webclient()
